`timescale 1ns/1ns

module tb_MSG_EXP ;

reg clock;
reg rst_n;

reg [511:0] msg_block;
reg block_start;

wire W_valid;
wire last_Wp_group;
wire last_W_group;
wire [31:0] W_j0, W_j1, W_j2;
wire [31:0] W_j_p0, W_j_p1, W_j_p2;

reg [31:0] W[0:67];
reg [31:0] Wp[0:63];
reg [5:0] cnt;

initial begin
    clock = 1'b0;
    forever begin
        #5 clock = ~clock;
    end
end

initial begin
    rst_n = 1'b0;
    #20 rst_n = 1'b1;
end

initial begin
    msg_block = 512'h0;
    block_start = 0;
    #30
    @(negedge clock) begin
        msg_block = 512'h61626380_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000018;
        block_start = 1;
    end
    @(negedge clock) begin
        msg_block = 512'h0;
        block_start = 0;
    end
    wait(last_W_group);
    #50;
    @(negedge clock) begin
        msg_block = 512'h61626380_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000018;
        block_start = 1;
    end
    @(negedge clock) begin
        msg_block = 512'h0;
        block_start = 0;
    end
    #10
    wait(last_W_group);
    #50;
    $finish;
end

always@(posedge clock) begin
    if(!rst_n || last_W_group)
        cnt <= 0;
    else if(W_valid)
        cnt <= cnt + 1;
end

generate
    genvar i;
    for(i = 0; i < 68; i = i + 3) begin
        always@(posedge clock) begin
            if(!rst_n) begin
                W[i] <= 0;
                W[i+1] <= 0;
                W[i+2] <= 0;
            end
            else if(cnt == i/3 && W_valid) begin
                W[i] <= W_j0;
                W[i+1] <= W_j1;
                W[i+2] <= W_j2;                
            end
        end
    end
    
    for(i = 0 ; i < 65; i = i + 3) begin
        always@(posedge clock) begin
            if(!rst_n) begin
                Wp[i] <= 0;
                Wp[i+1] <= 0;
                Wp[i+2] <= 0;
            end
            else if(cnt == i/3 && W_valid)begin
                Wp[i] <= W_j_p0;
                Wp[i+1] <= W_j_p1;
                Wp[i+2] <= W_j_p2;
            end
        end
    end
endgenerate

reg[31:0] j;
always@(posedge clock) begin
    if(last_W_group) begin
        #10 for( j = 0; j < 68; j = j + 1) begin
            $display("Wj[%d] = %8h",j,W[j]);
        end    
    end
end

reg[31:0] k;
always@(posedge clock) begin
    if(last_Wp_group) begin
        #10 for( k = 0; k < 64; k = k + 1) begin
            $display("Wj'[%d] = %8h",k,Wp[k]);
        end    
    end
end

MSG_EXP MSG_EXP_U0(
    .clk_i(clock),
    .rst_n_i(rst_n),

    .msg_block_i(msg_block),
    .block_start_i(block_start),

    .W_valid(W_valid),
    .last_Wp_group(last_Wp_group),
    .W_j0(W_j0),
    .W_j1(W_j1),
    .W_j2(W_j2),
    .W_j_p0(W_j_p0),
    .W_j_p1(W_j_p1),
    .W_j_p2(W_j_p2),
    .last_W_group(last_W_group)
);






endmodule //tb_MSG_EXP